# -*- coding: utf-8 -*-
import sys
import os
try:
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib
    import numpy as np  # 新增导入
except ImportError as e:
    print(f"导入失败: {e}")
    sys.exit(1)

# 设置中文字体
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False

class FreightAnalyzer:
    """
    货运数据分析核心类

    Attributes:
        df (pd.DataFrame): 装载后的货运数据
        data_dir (str): 数据文件目录路径
    """

    def __init__(self):
        # 动态获取当前文件所在目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        self.data_dir = os.path.join(current_dir, '练习一')  # 保存为实例变量
        
        try:
            # 构建完整文件路径
            excel_path = os.path.join(self.data_dir, 'FhjlViewDD.xlsx')
            print(f"加载文件: {excel_path}")
            
            if os.path.exists(excel_path):
                # 明确指定使用 openpyxl 引擎
                self.df = pd.read_excel(excel_path, engine='openpyxl')
                print("文件加载成功")
                
                # 打印列名用于调试
                print("数据框列名:", self.df.columns.tolist())
                print("前5行数据:")
                print(self.df.head())
                
                # 检查可能的日期列名变体
                date_col = None
                possible_names = ['日期', 'date', 'Date', '时间', '时间戳', 'Timestamp', '创建时间']
                for name in possible_names:
                    if name in self.df.columns:
                        date_col = name
                        break
                
                if date_col is None:
                    available_cols = ", ".join(self.df.columns.tolist())
                    raise KeyError(f"未找到日期列，可用列名: {available_cols}")
                
                print(f"使用 '{date_col}' 作为日期列")
                
                # 重命名列为标准名称
                self.df = self.df.rename(columns={date_col: '日期'})
                
                # 数据清洗
                self.df['日期'] = pd.to_datetime(self.df['日期'], errors='coerce')
                self.df = self.df.dropna(subset=['日期'])
                
                # 创建分析需要的列 - 关键修改
                # 1. 添加矿粉货运量
                self.df['矿粉货运量'] = self.df.apply(
                    lambda row: row['净重'] if row['货品'] == '矿粉' else 0, 
                    axis=1
                )
                
                # 2. 添加水泥货运量
                self.df['水泥货运量'] = self.df.apply(
                    lambda row: row['净重'] if row['货品'] == '水泥' else 0, 
                    axis=1
                )
                
                # 3. 添加总货运量
                self.df['总货运量'] = self.df['净重']
                
                # 4. 添加月份列
                self.df['月份'] = self.df['日期'].dt.month
                
                print(f"成功加载数据: {len(self.df)}条记录")
                print(f"数据时间范围: {self.df['日期'].min().date()} 至 {self.df['日期'].max().date()}")
                print(f"包含的月份: {sorted(self.df['月份'].unique())}")
            else:
                raise FileNotFoundError(f"数据文件不存在: {excel_path}")
        except Exception as e:
            print(f"数据加载失败: {e}")
            import traceback
            traceback.print_exc()
            sys.exit(1)

    def daily_trend(self, column, title):
        """生成日趋势图并保存"""
        try:
            # 检查数据中是否有目标月份的数据
            available_months = self.df['月份'].unique()
            if 6 not in available_months:
                print(f"警告: 数据中没有6月数据，可用月份: {available_months}")
                print(f"将使用最新月份数据进行分析: {max(available_months)}月")
                target_month = max(available_months)
            else:
                target_month = 6
            
            # 提取目标月份数据
            month_data = self.df[self.df['月份'] == target_month].copy()
            if month_data.empty:
                print(f"警告: 未找到{target_month}月{title}数据")
                return
                
            # 按日分组统计
            month_data['日期'] = month_data['日期'].dt.strftime('%m-%d')
            daily = month_data.groupby('日期', as_index=False)[column].sum()
            
            # 创建图表
            plt.figure(figsize=(12, 6))
            ax = daily.plot(x='日期', y=column, kind='bar', color='#2c7fb8')
            
            # 添加数据标签
            for p in ax.patches:
                ax.annotate(f"{int(p.get_height())}", 
                           (p.get_x() + p.get_width() / 2., p.get_height()),
                           ha='center', va='center', 
                           xytext=(0, 5), 
                           textcoords='offset points')
            
            plt.title(f'{target_month}月{title}日趋势', fontsize=15)
            plt.xlabel('日期')
            plt.ylabel(title)
            plt.xticks(rotation=45)
            plt.tight_layout()
            
            # 保存图片到数据目录
            save_path = os.path.join(self.data_dir, f'{target_month}月{title}日趋势.png')
            plt.savefig(save_path)
            print(f"已保存图表: {save_path}")
            plt.close()
            return save_path
        except Exception as e:
            print(f"生成{title}趋势图时出错: {e}")
            return None

    def generate_report(self):
        """生成分析报告"""
        try:
            # 客户分析
            top_clients = self.client_analysis().head(5)
            # 地区分析
            top_locations = self.location_analysis().head(5)
            
            # 报告路径
            report_path = os.path.join(self.data_dir, 'A公司货运情况分析.md')
            
            with open(report_path, 'w', encoding='utf-8') as f:
                f.write('# A公司货运分析报告\n\n')
                f.write('## 数据概览\n')
                f.write(f"- 总记录数: {len(self.df)}条\n")
                f.write(f"- 数据时间范围: {self.df['日期'].min().date()} 至 {self.df['日期'].max().date()}\n\n")
                
                # 动态获取实际分析的月份
                target_month = 6 if 6 in self.df['月份'].unique() else max(self.df['月份'].unique())
                
                f.write(f'## {target_month}月货运趋势分析\n')
                f.write(f'### 每日矿粉货运趋势\n')
                f.write(f'![矿粉趋势]({target_month}月矿粉货运量日趋势.png)\n\n')
                
                f.write(f'### 每日水泥货运趋势\n')
                f.write(f'![水泥趋势]({target_month}月水泥货运量日趋势.png)\n\n')
                
                f.write('## 客户分析\n')
                f.write('| 排名 | 客户名称 | 总货运量(吨) |\n')
                f.write('|------|----------|--------------|\n')
                for i, (client, amount) in enumerate(top_clients.items(), 1):
                    f.write(f'| {i} | {client} | {amount:.0f} |\n')
                f.write('\n')
                
                f.write('## 发货地分析\n')
                f.write('| 排名 | 发货地 | 总货运量(吨) |\n')
                f.write('|------|--------|--------------|\n')
                for i, (location, amount) in enumerate(top_locations.items(), 1):
                    f.write(f'| {i} | {location} | {amount:.0f} |\n')
            
            print(f"已生成报告: {report_path}")
            return report_path
        except Exception as e:
            print(f"生成报告时出错: {e}")
            return None

    def client_analysis(self):
        """客户货运量分析"""
        return self.df.groupby('客户')['总货运量'].sum().sort_values(ascending=False)  # 修改列名

    def location_analysis(self):
        """发货地货运量分析"""
        return self.df.groupby('发货地')['总货运量'].sum().sort_values(ascending=False)

if __name__ == '__main__':
    analyzer = FreightAnalyzer()
    analyzer.daily_trend('矿粉货运量', '矿粉货运量')
    analyzer.daily_trend('水泥货运量', '水泥货运量')
    analyzer.generate_report()